package com.divemotor.ventarepuestosinternet.dao.impl;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.divemotor.ventarepuestosinternet.beans.adapter.PromocionAdapter;
import com.divemotor.ventarepuestosinternet.beans.form.PromocionGestionForm;
import com.divemotor.ventarepuestosinternet.dao.PromocionDAO;
import com.divemotor.ventarepuestosinternet.model.Moneda;
import com.divemotor.ventarepuestosinternet.model.Promocion;
import com.divemotor.ventarepuestosinternet.model.TipoPromocion;
import com.divemotor.ventarepuestosinternet.util.Constantes;
import com.divemotor.ventarepuestosinternet.util.DatosDeSession;
import com.divemotor.ventarepuestosinternet.util.FechasUtil;

@SuppressWarnings("unchecked")
@Repository(value="promocionDAO")
public class PromocionDAOImpl implements PromocionDAO, Serializable {


	private static final long serialVersionUID = -7321728315299291367L;
	
	@Autowired
	private SessionFactory sessionFactory;

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	private void construirProyeccionPromocion(Criteria criteria){
		ProjectionList lista = Projections.projectionList();
		lista.add(Projections.property("idPromocion"), "idPromocion");
		lista.add(Projections.property("codigo"), "codigo");
		lista.add(Projections.property("nombre"),"nombre");
		lista.add(Projections.property("estado"),"estado");
		lista.add(Projections.property("tipo.nombre"),"tipo");
		criteria.setProjection(lista);
	}

	@Override
	public List<PromocionAdapter> buscarAdapter(PromocionGestionForm promocionForm) {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Promocion.class,"promocion")
										  .add(Restrictions.eq("promocion.pais", DatosDeSession.obtenerPaisDelUsuarioAutenticado()))
										  .addOrder(Order.asc("promocion.nombre"));
		criteria.createAlias("promocion.tipoPromocion", "tipo");
		
		construirProyeccionPromocion(criteria);
		
		String porc = Constantes.PORCENTAJE;
		
		String codigo = promocionForm.getCodigo();
		if(StringUtils.isNotBlank(codigo)){
			criteria.add(Restrictions.like("codigo",porc + codigo + porc).ignoreCase());
		}
		
		String nombre = promocionForm.getNombre();
		if(StringUtils.isNotBlank(nombre)){
			criteria.add(Restrictions.like("nombre",porc + nombre + porc).ignoreCase());
		}
		
		Integer tipoPromocion = promocionForm.getTipoPromocion();
		if(tipoPromocion != Constantes.NO_SELECCIONADO){
			criteria.add(Restrictions.eq("tipoPromocion.idTipoPromocion", tipoPromocion));
		}
		
		String estado = promocionForm.getEstado();
		if(!Constantes.STR_NO_SELECCIONADO.equals(estado)){
			criteria.add(Restrictions.eq("estado", estado));
		}else{			
			criteria.add(Restrictions.not(Restrictions.eq("estado", Constantes.ESTADO_ELIMINADO)));
		}
		
		criteria.setResultTransformer(Transformers.aliasToBean(PromocionAdapter.class));
		return criteria.list();
	}

	@Override
	public String obtenerMaximoNombreImagen() {
		Query query = sessionFactory.getCurrentSession().createQuery("SELECT MAX(urlImagen) FROM Promocion");
		String nombreImagen = (String) query.list().get(0);
		if (nombreImagen == null) {
			nombreImagen = Constantes.PRIMER_NOMBRE_IMAGEN;
		}
		return nombreImagen;
	}

	@Override
	public Promocion obtenerPorId(Integer idPromocion) {
		return (Promocion) sessionFactory.getCurrentSession().get(Promocion.class, idPromocion);
	}

	@Override
	public void insertar(Promocion promocion) {
		Session sesion = getSessionFactory().getCurrentSession();
		promocion.setMoneda((Moneda)sesion.load(Moneda.class, promocion.getIdMoneda()));
		promocion.setTipoPromocion((TipoPromocion)sesion.load(TipoPromocion.class, promocion.getIdTipoPromocion()));
		getSessionFactory().getCurrentSession().persist(promocion);
	}

	@Override
	public void actualizar(Promocion promocion) {
		Session sesion = getSessionFactory().getCurrentSession();
		promocion.setMoneda((Moneda)sesion.load(Moneda.class, promocion.getIdMoneda()));
		promocion.setTipoPromocion((TipoPromocion)sesion.load(TipoPromocion.class, promocion.getIdTipoPromocion()));
		sessionFactory.getCurrentSession().merge(promocion);
	}

	@Override
	public List<Promocion> listarVigentesPorTipo(Integer idTipoPromocion) {
		
		Date fecha = FechasUtil.obtenerFechaActual();
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Promocion.class,"promocion")
										  .add(Restrictions.eq("promocion.pais", DatosDeSession.obtenerPaisDelUsuarioAutenticado()))
										  .add(Restrictions.le("promocion.fechaInicio", fecha))
										  .add(Restrictions.ge("promocion.fechaFin", fecha))
										  .add(Restrictions.eq("promocion.estado", Constantes.ESTADO_ACTIVO));
		
		if(Constantes.NO_SELECCIONADO != idTipoPromocion){
			criteria.add(Restrictions.eq("promocion.tipoPromocion.idTipoPromocion", idTipoPromocion));
		}
		
		return criteria.list();
	}

	@Override
	public List<Promocion> listarPromocionPorCodigo(Promocion promocion) {
		return getSessionFactory().getCurrentSession().createQuery("SELECT p FROM Promocion p WHERE upper(p.codigo) = upper(:codigo)")
				.setParameter("codigo", promocion.getCodigo()).list();
	}
}